package com.wasion.pwportable.protocol.composer;

import com.wasion.core.util.CRC16;
import com.wasion.core.util.ConverterXBaseUtil;
import com.wasion.pwportable.protocol.Protocol;

public class FrameComposerImp implements FrameComopserIF {

	protected String dataBytes = "";
	protected String identifier = "";
	protected String dataLength = "";
	protected String sourceAddr = "";
	protected String targetAddr = "";
	protected static String crc = "";

	private static FrameComposerImp instance;

	public synchronized static FrameComposerImp getInstance() {
		if (instance == null) {
			instance = new FrameComposerImp();
		}
		return instance;
	}

	private FrameComposerImp() {

	}

	// 读数据的没有数据域
	public String composeFrame(String actionId) {
		StringBuffer messageString = new StringBuffer();
		// 创建一个由主站发出的帧
		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(Protocol.READ_FRAME_LENGTH);
		messageString.append(Protocol.SENDERID);
		messageString.append(actionId);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	// 组成一个 写数据的帧方法
	public String composeFrame(String actionId, String dataBytes) {

		int len = 9 + dataBytes.length() / 2;

		String dataLength = Integer.toHexString(len);

		if (dataLength.length() == 1) {
			dataLength = "0" + dataLength;
		}

		StringBuffer messageString = new StringBuffer();
		// 创建一个由主站发出的帧
		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(dataLength.toUpperCase());
		messageString.append(Protocol.SENDERID);
		messageString.append(actionId);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);
		messageString.append(dataBytes.toUpperCase());

		String crc = makeCRC(messageString);
		messageString.append(crc);

		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	public String getChannelCommand(int channel) {

		StringBuffer messageString = new StringBuffer();
		messageString.append(Protocol.FRAEMHEAD);

		messageString.append(Protocol.GET_Channel_IDENTIFIER);

		String channel_byte = Protocol.channels[channel] + "00"
				+ Protocol.channels[channel];

		messageString.append(channel_byte);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	/**
	 * @param messageString
	 * @return
	 */
	public String makeCRC(StringBuffer messageString) {
		byte[] hexBytes = ConverterXBaseUtil.hexStringToByteArray(messageString
				.toString());
		String crc = CRC16.calc(hexBytes).toUpperCase();
		return crc;
	}

	public String makeFileRequest() {
		StringBuffer messageString = new StringBuffer();

		String fileName = "AAAABBBB"; // ASCII文件名 4个字节
		String fileSize = "0000BBBB"; // 文件大小 4个字节

		String totalLines = "FFFF"; // 文件总段(行)数 2个字节
		String recieved = "0000"; // 已接收文件段数 2个字节
		String fileCRC = "CCCC"; // 文件总校验 2个字节

		String fileDate = fileName + fileSize + totalLines + recieved + fileCRC;

		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(Protocol.FILE_REQUEST_LENGTH);
		messageString.append(Protocol.SENDERID);
		messageString.append(Protocol.FILE_REQUEST_IDENTIFIER);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);

		messageString.append(fileDate);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	public String makePreUpdate() {
		StringBuffer messageString = new StringBuffer();

		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(Protocol.PREUPDATE_LENGTH);
		messageString.append(Protocol.SENDERID);
		messageString.append(Protocol.PREUPDATE_IDENTIFIER);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);
		messageString.append(Protocol.PREUPDATE_REQUEST);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	public String makeRestart() {
		StringBuffer messageString = new StringBuffer();

		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(Protocol.RESTART_LENGTH);
		messageString.append(Protocol.SENDERID);
		messageString.append(Protocol.RESTART_IDENTIFIER);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	// 多级，单点 抄读 状态信息
	public String makeRoutedStatus(String[] nodes) {
		StringBuffer messageString = new StringBuffer();
		String route = "";
		String target = "FFFFFF";
		String relayGrade = "01";
		String length = "09";
		String dataValidatebit = "01";
		int nodeCount = nodes.length;

		switch (nodeCount) {
		case 1:
			length = "09";
			relayGrade = "09";
			dataValidatebit = "01";
			route = nodes[0];
			break;
		case 2:
			target = nodes[1];
			length = "0C";
			relayGrade = "0A";
			dataValidatebit = "03";
			route = nodes[0] + nodes[1];

			break;
		case 3:
			target = nodes[2];
			length = "0F";
			relayGrade = "0B";
			dataValidatebit = "07";
			route = nodes[0] + nodes[1] + nodes[2];
			break;
		case 4:
			target = nodes[3];
			length = "12";
			relayGrade = "0C";
			dataValidatebit = "0F";
			route = nodes[0] + nodes[1] + nodes[2] + nodes[3];
			break;
		case 5:
			target = nodes[4];
			length = "15";
			relayGrade = "0D";
			dataValidatebit = "1F";
			route = nodes[0] + nodes[1] + nodes[2] + nodes[3] + nodes[4];
			break;
		case 6:
			target = nodes[5];
			length = "18";
			relayGrade = "0E";
			dataValidatebit = "3F";
			route = nodes[0] + nodes[1] + nodes[2] + nodes[3] + nodes[4]
					+ nodes[5];

			break;
		case 7:
			target = nodes[6];
			length = "1B";
			relayGrade = "0F";
			dataValidatebit = "7F";
			route = nodes[0] + nodes[1] + nodes[2] + nodes[3] + nodes[4]
					+ nodes[5] + nodes[6];
			break;

		default:
			break;
		}

		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(length);
		messageString.append(Protocol.SENDERID);
		messageString.append(Protocol.STATUS_RD);
		messageString.append(relayGrade);
		messageString.append(dataValidatebit);
		messageString.append(route);

		String crc = makeCRC(messageString);

		messageString.append(crc);
		messageString.append(Protocol.FRAMETAIL);

		return messageString.toString();
	}

	public String makeUpdate(String frame_length, String data) {
		StringBuffer messageString = new StringBuffer();
		messageString.append(Protocol.FRAEMHEAD);
		messageString.append(frame_length); // variable length, requiring
		messageString.append(Protocol.SENDERID);
		messageString.append(Protocol.UPDATE_IDENTIFIER);
		messageString.append(Protocol.RELAY_GRADE);
		messageString.append(Protocol.VALIDATE_BIT);
		messageString.append(Protocol.RECEIVERID);
		messageString.append(data); // data to be update

		String crc = makeCRC(messageString);
		messageString.append(crc);

		messageString.append(Protocol.FRAMETAIL);
		return messageString.toString();
	}

	@Override
	public String composeInnerFrame(String actionId, String data) {

		StringBuffer buffer = new StringBuffer();
		buffer.append(Protocol.FRAEMHEAD);

		int len = ((actionId.length() == 1 ? "0" + actionId : actionId) + data)
				.length() / 2;
		String lenStr = (len + "") .length() == 1 ? ("0" + len) : (len + "");
		buffer.append(lenStr); // variable length, requiring
		buffer.append(actionId);
		buffer.append(data); // data to be update

		String crc = makeCRC(buffer);
		buffer.append(crc);

		buffer.append(Protocol.FRAMETAIL);
		return buffer.toString();
	}

}
